home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
zmdm_src.arc
/
EXPANDAR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-06-26
|
14KB
|
701 lines
/*
* Examine each argument given to expandargs()
* If it is a directory, then expand it
* to all its component files, recursively
* till you bottom out.
* If it is not a directory, then just pass it on.
*
* Inputs: routine, argc, argv
* Outputs: nargc, nargv (calls routine(nargc, nargv))
* To test: compile with -DTEST
* define MWC if using Mark Williams C
* run with a directory as an arg
* Author: JRB bammi@mandrill.ces.CWRU.edu
* Requirements: Mark Williams C or Alcyon C
* Wants lots of Dynamic memory. It
* all depends upon how many files you
* have. Use the -P option to prune
* out subdirectories and do things
* one at a time, if you keep running
* out of memory.
* With Mark Williams i use _stksize = 128K
* With Alcyon i use memory model 2 (half of
* of avail memory) in GEMSTART.S
*
* WARNINGS: Be CAREFUL about the 40 folder bug. Use
* GEMBOOT or FOLDRXXX when dealing with
* a deeply nested file structure.
*
* Added -P name prune option at the suggestion of dietz@zhmti
* Multiple -P's may be given on the command line.
* -P name may be given anywhere on the command line. -P name
* will prune the subdirectories named as arguement to -P.
* ie: when the program is decending the file hierarchy it
* will not visit the pruned branches.
* NOTE that the option is -P and not -p
* (-p is a valid sz option).
* NOTE that the arguement given to -P can be the name
* of a file or a directory. In case it is a file,
* that file is skipped.
*
*/
/*
* Expand argc, so that the called routine(nargc,nargv) receives only
* filenames, in nargv[][]
*
************************************************************************
* *
* WARNING: Be CAREFUL about the 40 folder bug. Use *
* GEMBOOT or FOLDRXXX when dealing with *
* a deeply nested file structure. *
* *
************************************************************************
*
* Jwahar R. Bammi
* usenet: mandrill!bammi@{decvax,sun}.UUCP
* csnet: bammi@mandrill.ces.CWRU.edu
* arpa: bammi@mandrill.ces.CWRU.edu
* CompuServe: 71515,155
*
*/
#ifdef TEST
#include <stdio.h>
#include <osbind.h>
#include <ctype.h>
#endif
#ifdef TRUE
#undef TRUE
#endif
#ifdef OK
#undef OK
#endif
#ifdef FALSE
#undef FALSE
#endif
#define TRUE 1
#define OK 0
#define FALSE 0
#define Realloc realloc
#ifdef TEST
struct stat
{
char st_sp1[21]; /* Junk */
char st_mode; /* File attributes */
int st_time; /* Mod Time */
int st_date; /* Mod date */
long st_size; /* File size */
char st_name[14]; /* File name */
};
#endif
typedef struct _prunelist {
char *name; /* name of subdirectory to prune */
struct _prunelist *next; /* ptr to next */
} PRUNELIST;
static char *ProgName;
static PRUNELIST *PruneList = (PRUNELIST *)NULL; /* Head of PruneList */
static char **CopyToNargv();
static char **ExpandStack();
static void FreeStack();
static void FreeNargv();
static void FreePrune();
static void FreeUp();
static int PushDir();
static char *PopDir();
static int ProcessDirs();
static PRUNELIST *AddPrune();
static int OnPruneList();
static int isdir();
extern int existd();
expandargs(routine, argc, argv)
int (*routine)();
int argc;
char **argv;
{
register int status;
int nargc;
char **nargv;
extern char **CopyToNargv();
extern PRUNELIST *AddPrune();
extern int existd();
nargc = 0;
nargv = (char **)NULL;
ProgName = *argv;
/* copy argv[0] blindly */
if((nargv = CopyToNargv(*argv, nargc, nargv)) == (char **)NULL)
{
FreeUp(nargc, nargv);
return(~OK);
}
nargc++;
while((--argc) > 0)
{
argv++;
if(**argv == '-')
{
/* copy any options except -P */
#ifdef TEST
/* some shell pass -P as -p */
if( ((*argv)[1] == 'P') || ((*argv)[1] == 'p'))
#else
if( (*argv)[1] == 'P')
#endif
{
if((--argc) <= 0)
{
fprintf(STDERR,"no argument given to -P\n");
FreeUp(nargc, nargv);
return(~OK);
}
if((PruneList = AddPrune(PruneList,*++argv))
== (PRUNELIST *)NULL)
{
FreeUp(nargc, nargv);
return(~OK);
}
}
else
{
if((nargv = CopyToNargv(*argv, nargc, nargv))
== (char **)NULL)
{
FreeUp(nargc, nargv);
return(~OK);
}
else
nargc++;
}
}
else
{
/* If its not on the PruneList then */
if(!OnPruneList(PruneList, *argv))
{
/* if it is a directory, push it */
if(existd(*argv))
{
if((status = PushDir(*argv)) != OK)
{
FreeUp(nargc, nargv);
return(status);
}
}
else
{
/* it is NOT a directory, copy to nargv */
if((nargv = CopyToNargv(*argv, nargc, nargv))
== (char **)NULL)
{
FreeUp(nargc, nargv);
return(~OK);
}
else
nargc++;
}
}
}
} /* while */
/* process pushed directories if any */
if((status = ProcessDirs(&nargc, &nargv)) != OK)
{
FreeUp(nargc, nargv);
return(status);
}
/* else Free the Stack and Prune List, call *routine */
FreeStack();
FreePrune();
status = (*routine)(nargc, nargv);
FreeNargv(nargc, nargv);
return status;
}
/*
* Expand nargv by an element and copy a String into the new element
*
*/
static char **CopyToNargv(string, nargc, nargv)
char *string;
int nargc;
char **nargv;
{
extern char *malloc(), *Realloc(), *strcpy();
extern int strlen();
/* expand nargv by 1 element */
if(nargv == (char **)NULL)
/* do it with malloc for the first one */
nargv = (char **)malloc(sizeof(char **));
else
/* do it with Realloc for others */
nargv = (char **)Realloc(nargv, (nargc+1)*sizeof(char **));
if(nargv == (char **)NULL)
{
/* failed to get memory */
fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
return ((char **)NULL);
}
/* Get mem for string */
if(( nargv[nargc] = malloc(strlen(string)+1)) == (char *)NULL)
{
/* failed to get memory */
fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
return ((char **)NULL);
}
/* copy string into nargv[nargc] */
(void)strcpy( nargv[nargc], string);
return(nargv);
}
static char **Stack = (char **)NULL; /* directory stack */
static char StackSize = 0; /* Size of current Stack */
static int Top = -1;
#define STACK_EMPTY (Top < 0)
#define CHUNKSIZE 16
/*
* Grow the Stack by one chunk of CHUNKSIZE elements
*
*/
static char **ExpandStack(Stack)
char **Stack;
{
extern char *malloc(), *Realloc();
/* Grow Stack */
if(Stack == (char **)NULL)
/* with malloc */
Stack = (char **)malloc(CHUNKSIZE * sizeof(char **));
else
/* with Realloc */
Stack = (char **)Realloc(Stack, (StackSize+CHUNKSIZE) *
sizeof(char **));
if(Stack == (char **)NULL)
{
/* outa mem */
fprintf(STDERR,"%s(ExpandStack()): Out of Memory\n", ProgName);
return((char **)NULL);
}
StackSize += CHUNKSIZE;
return(Stack);
}
/*
* Free the Stack
*
*/
static void FreeStack()
{
if(StackSize > 0)
(void)free(Stack);
Stack = (char **)NULL;
StackSize = 0;
Top = -1;
}
/*
* Free Nargv
*
*/
static void FreeNargv(nargc, nargv)
int nargc;
char *nargv[];
{
register int i;
for(i = 0; i < nargc; i++)
(void)free(nargv[i]);
if(nargc > 0)
(void)free(nargv);
}
/*
* Free the PruneList
*
*/
static void FreePrune()
{
register PRUNELIST *p, *next;
for(p = PruneList; p != (PRUNELIST *)NULL; p = next)
{
next = p->next;
(void)free(p);
}
PruneList = (PRUNELIST *)NULL;
}
/*
* FreeUp before bad exit
*
*/
static void FreeUp(nargc, nargv)
int nargc;
char **nargv;
{
FreeStack();
FreePrune();
FreeNargv(nargc, nargv);
}
/*
* Push a directory name on Stack
*
*/
static int PushDir(name)
char *name;
{
extern char *malloc(), *strcpy();
extern int strlen();
extern char **ExpandStack();
#ifdef DDEBUG
printf("PushDir: %s\n", name);
#endif
++Top;
if(Top >= StackSize)
{
if((Stack = ExpandStack(Stack)) == (char **)NULL)
return(~OK);
}
if((Stack[Top] = malloc(strlen(name)+1)) == (char *)NULL)
{
/* outa mem */
fprintf(STDERR,"%s(PushDir()): Out of